#include <kernel.h>

#define SCHED_LEVEL_COUNT 32
volatile static struct sched_node_s cpu_run_pool[SCHED_LEVEL_COUNT];
volatile static uint32_t            cpu_run_mask;
int
sched_init(void)
{
	 int i;
	 for (i = 0; i != SCHED_LEVEL_COUNT; ++ i)
	 {
		  cpu_run_mask = 0;
		  cpu_run_pool[i].prev =
			   cpu_run_pool[i].next =
			   (struct sched_node_s *)&cpu_run_pool[i];
	 }
}

void
sched_init_node(struct sched_node_s *node, uint32_t level)
{
	 node->level = level;
	 node->next = node->prev = node;
}

struct sched_node_s *
sched_pick(void)
{
	 struct sched_node_s *result;
	 if (cpu_run_mask == 0)
		  result = NULL;
	 else
	 {
		  result = cpu_run_pool[bsr(cpu_run_mask)].next;
	 }
	 return result;
}

void
sched_insert(struct sched_node_s *node)
{
	 if (node->next == node)
	 {
		  node->prev = cpu_run_pool[node->level].prev;
		  node->next = (struct sched_node_s *)&cpu_run_pool[node->level];
		  
		  node->prev->next = node;
		  node->next->prev = node;

		  cpu_run_mask |= 1 << node->level;
	 }
}

void
sched_remove(struct sched_node_s *node)
{
	 if (node->next != node)
	 {
		  if (node->next == node->prev)
			   cpu_run_mask ^= 1 << node->level;
		  
		  node->prev->next = node->next;
		  node->next->prev = node->prev;
		  
		  node->next = node->prev = node;
	 }
}

int
sched_should_yield(struct sched_node_s *node)
{
	 return node->level < bsr(cpu_run_mask);
}
	 
